package disk;

/**
 *
 * @author eagle
 */
import eduni.simanim.*;
import eduni.simjava.*;
import eduni.simjava.distributions.*;

class Source1 extends Sim_entity {

    private Sim_port out;
    private Sim_negexp_obj delay;

    Source1(String name, int x, int y, String image, double mean) {
        super(name, image, x, y);
        out = new Sim_port("Out", "port", Anim_port.RIGHT, 40);
        add_port(out);
        delay = new Sim_negexp_obj("Delay", mean);
        add_generator(delay);
    }

    @Override
    public void body() {
        while (Sim_system.running()) {
            sim_schedule(out, 0.0, 0);
            sim_trace(1, "S Out");
            sim_pause(delay.sample());
        }
    }
}

class Sink extends Sim_entity {

    private Sim_port in, out1, out2;
    private Sim_normal_obj delay;
    private Sim_random_obj prob;
    private Sim_stat stat;

    Sink(String name, int x, int y, String image, double mean, double var) {
        super(name, image, x, y);
        in = new Sim_port("In", "port", Anim_port.LEFT, 40);
        out1 = new Sim_port("Out1", "port", Anim_port.RIGHT, 20);
        out2 = new Sim_port("Out2", "port", Anim_port.RIGHT, 60);
        add_port(in);
        add_port(out1);
        add_port(out2);
        delay = new Sim_normal_obj("Delay", mean, var);
        prob = new Sim_random_obj("Probability");
        add_generator(delay);
        add_generator(prob);
        stat = new Sim_stat();
        stat.add_measure(Sim_stat.THROUGHPUT);
        stat.add_measure(Sim_stat.RESIDENCE_TIME);
        stat.add_measure("Thread use", Sim_stat.STATE_BASED, false);
        stat.calc_proportions("Thread use", new double[]{0, 1, 2, 3, 4});
        set_stat(stat);
    }

    @Override
    public void body() {
        while (Sim_system.running()) {
            Sim_event e = new Sim_event();
            sim_get_next(e);
            double before = Sim_system.sim_clock();
            sim_process(delay.sample());
            sim_completed(e);
            double p = prob.sample();
            if (p < 0.15) {
                stat.update("Thread use", 1, before, Sim_system.sim_clock());
            } else if (p < 0.75) {
                stat.update("Thread use", 2, before, Sim_system.sim_clock());
            } else {
                stat.update("Thread use", 3, before, Sim_system.sim_clock());
            }
            p = prob.sample();
            if (p < 0.60) {
                sim_schedule(out1, 0.0, 1);
                sim_trace(1, "S Out1");
            } else {
                sim_schedule(out2, 0.0, 1);
                sim_trace(1, "S Out2");
            }
        }
    }
}

class Disk extends Sim_entity {

    private Sim_port in;
    private Sim_normal_obj delay;
    private Sim_stat stat;

    Disk(String name, int x, int y, String image, double mean, double var) {
        super(name, image, x, y);
        in = new Sim_port("In", "port", Anim_port.LEFT, 40);
        add_port(in);
        delay = new Sim_normal_obj("Delay", mean, var);
        add_generator(delay);
        stat = new Sim_stat();
        stat.add_measure(Sim_stat.UTILISATION);
        set_stat(stat);
        add_param(new Anim_param("Busy", Anim_param.STATE, "idle", 0, 0));
    }

    @Override
    public void body() {
        while (Sim_system.running()) {
            Sim_event e = new Sim_event();
            sim_get_next(e);
            sim_trace(1, "P busy");
            sim_process(delay.sample());
            sim_trace(1, "P idle");
            sim_completed(e);
        }
    }
}
